/*
 * Missile.cpp
 *
 *  Created on: 19.10.2013
 *      Author: dima
 */

#include "MissileModel.hpp"
#include "TankModel.hpp"

#include <string>


std::map<Tanks::Model::MissileModel *, Tanks::Model::TankModel *> m_missiles;

std::map<Tanks::Model::MissileModel *, Tanks::Model::TankModel *>::iterator
Tanks::
Model::
MissileModel::
Begin()
{
  return m_missiles.begin();
}

std::map<Tanks::Model::MissileModel *, Tanks::Model::TankModel *>::iterator
Tanks::
Model::
MissileModel::
End()
{
  return m_missiles.end();
}

void
Tanks::
Model::
MissileModel::
MissileExploded(Tanks::Model::MissileModel * argMissile)
{
  m_missiles.erase(argMissile);
  delete argMissile;
}


Tanks::
Model::
MissileModel::
MissileModel(int argX,
             int argY,
             int argTeam,
             Tanks::Model::TankModel * argOwnerTank) :
                m_exploding(false),
                m_XVelocity(0),
                m_YVelocity(0),
                m_explosionStartTime(0),
                m_explosionDuration(32), // 32 ticks are ca 0.5 sec
                m_direction(DirectionEnd)

{
  m_team = argTeam;
  m_type = Missile;
  m_rect = new SDL_Rect;
  m_rect->x = argX;
  m_rect->y = argY;
  m_rect->w = 10;
  m_rect->h = 10;
  CollisionModel & collisionModel = CollisionModel::getInstance();
  collisionModel.RegisterObject(this);
  m_missiles.insert(std::pair<MissileModel *, TankModel *>(this, argOwnerTank));
}

Tanks::
Model::
MissileModel::
~MissileModel()
{
  CollisionModel & collisionModel = CollisionModel::getInstance();
  collisionModel.RemoveObject(this);
}

void
Tanks::
Model::
MissileModel::
Tick()
{
  ++m_ticks;
  if(m_exploding)
  {
    if(m_ticks - m_explosionStartTime >= m_explosionDuration)
    {
      m_exploding = false;
      MissileExploded(this);
    }
    return;
  }
  if((m_XVelocity == 0  &&
      m_YVelocity == 0))
  {
    return;
  }
  m_rect->x += m_XVelocity;
  m_rect->y += m_YVelocity;
  if((m_rect->x < 0) ||
     (m_rect->y < 0) ||
     (m_rect->x + m_rect->w > 1024) ||
     (m_rect->y + m_rect->h > 768))
  {
    MissileExploded(this);
    return;
  }

  CollisionModel & collisionModel = CollisionModel::getInstance();
  collisionModel.CheckCollision(this);
}

void
Tanks::
Model::
MissileModel::
Collision(Tanks::Model::GameObjectModel * argGameObject,
      Tanks::Model::CollisionModel::CollisionSide argCollisionSide,
      bool argActive)
{
  if(m_missiles.at(this) == argGameObject
  || !argActive)
  { // no collision with your owner-tank
    return;
  }
  GameObjectType type = argGameObject->GetType();
  if(type == SolidBlock ||
   ((type >= Player && type <= TankHard) &&
     m_team != argGameObject->GetTeam()))
  {
    m_exploding = true;
    m_explosionStartTime = m_ticks;
    m_XVelocity = m_YVelocity = 0;
  }
}


void
Tanks::
Model::
MissileModel::
SetDirection(Tanks::Model::Direction argDirection, int argVelocity)
{
  switch(argDirection)
  {
  case DirectionLeft:
    m_XVelocity = -argVelocity;
    break;
  case DirectionUp:
    m_YVelocity = -argVelocity;
    break;
  case DirectionRight:
    m_XVelocity = argVelocity;
    break;
  case DirectionDown:
    m_YVelocity = argVelocity;
    break;
  default:
    throw std::string("SetDirection in MissilModel (Invalid Direction)");
    break;
  }
  m_direction = argDirection;
}



